using System;
using System.Diagnostics;
using System.Globalization;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Resources;
using Windows.Globalization;
using Windows.Storage;
using Windows.UI.ApplicationSettings;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using com.IronOne.BoardPACWinApp.Common;
using com.IronOne.BoardPACWinApp.View.Page;
using com.IronOne.BoardPACWinApp.View.UserControl;
using CompleteReader;
using CompleteReader.Settings;
using Microsoft.ApplicationInsights;
using pdftron;
using pdftron.Common;
using SuspensionManager = CompleteReader.Common.SuspensionManager;
using SuspensionManagerException = CompleteReader.Common.SuspensionManagerException;

namespace com.IronOne.BoardPACWinApp
{
    /// <summary>
    ///     Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App
    {
        /// <summary>
        ///     Initializes the singleton application object.  This is the first line of authored code
        ///     executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            InitializeComponent();

            Suspending += OnSuspending;
            UnhandledException += Application_UnhandledException;

            WindowsAppInitializer.InitializeAsync("6d4cbf37-df6e-40b1-8035-433513adf351");

            var culture = new CultureInfo("en-US");
            ApplicationLanguages.PrimaryLanguageOverride = culture.Name;
            CultureInfo.DefaultThreadCurrentCulture = culture;
            CultureInfo.DefaultThreadCurrentUICulture = culture;

            //DispatcherHelper.Initialize(); //This method should be called once on the UI thread to ensure that the UIDispatcher property is initialized.

            //pdftron.PDFNet.Initialize("");
            //pdftron.PDFNet.SetViewerCache(100 * 1024 * 1024, false);
            //pdftron.PDFNet.SetDefaultDiskCachingEnabled(true);
            //string res_path = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
            //pdftron.PDFNet.SetResourcesPath(res_path);
            //pdftron.PDFNet.SetPersistentCachePath(res_path);

            #region PDFTron Support team's code

            try
            {
                PDFNet.Initialize();
            }
            catch (Exception e)
            {
                var ex = new PDFNetException(e.HResult);
                if (ex.IsPDFNetException)
                {
                    Debug.WriteLine(ex.ToString());
                }
            }

            PDFNet.SetViewerCache(0, false);

            #endregion

            /*try
            {
                uint numthumbs = 25;
                pdftron.Common.RecentlyUsedCache.InitializeRecentlyUsedCache(numthumbs, numthumbs * 2 * 1024 * 1024, 0.3);
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("Failed to initialize RecentlyUsedCache: " + e.Message);
            }*/
        }

        /// <summary>
        ///     Invoked when the application is launched normally by the end user.  Other entry points
        ///     will be used when the application is launched to open a specific file, to display
        ///     search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            var rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof (SplashPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
            //DispatcherHelper.Initialize();
        }

        protected override void OnFileActivated(FileActivatedEventArgs args)
        {
            var rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active

            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();
                // Associate the frame with a SuspensionManager key
                SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    // Restore the saved session state only when appropriate
                    try
                    {
                        //await CompleteReader.Common.SuspensionManager.RestoreAsync();
                    }
                    catch (SuspensionManagerException)
                    {
                        //Something went wrong restoring state.
                        //Assume there is no state and continue
                    }
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            var p = rootFrame.Content as DocumentsPage;
            if (p == null)
            {
                if (!rootFrame.Navigate(typeof (DocumentsPage)))
                {
                    throw new Exception("Failed to create initial page. Why?");
                }
                p = rootFrame.Content as DocumentsPage;
            }
            if (p != null)
            {
                p.OpenFileFromLaunch(args.Files[0] as StorageFile);
            }

            // Ensure the current window is active
            Window.Current.Activate();
        }

        /// <summary>
        ///     Invoked when application execution is being suspended.  Application state is saved
        ///     without knowing whether the application will be terminated or resumed with the contents
        ///     of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }

        protected override void OnWindowCreated(WindowCreatedEventArgs args)
        {
            SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;
        }

        private void OnCommandsRequested(SettingsPane settingsPane, SettingsPaneCommandsRequestedEventArgs e)
        {
            var loader = ResourceLoader.GetForCurrentView();

            var generalCommand = new SettingsCommand("General Settings", "General Settings", handler =>
            {
                var generalSettings = new GeneralSettingsFlyout();
                generalSettings.Show();
            });
            e.Request.ApplicationCommands.Add(generalCommand);

            //Following pages does not need of following settings
            var pageName = ((Frame) Window.Current.Content).CurrentSourcePageType.Name;
            if (!pageName.Equals("SplashPage") && !pageName.Equals("LoginPage") && !pageName.Equals("ErrorPage") &&
                !pageName.Equals("WipedOutPage") && !pageName.Equals("SettingsPage"))
            {
                var userSettingsCommand = new SettingsCommand("UserSettings", "User Settings", handler =>
                {
                    //UserSettingsFlyout userSettings = new UserSettingsFlyout();
                    //userSettings.Show();

                    var frame = (Frame) Window.Current.Content;
                    var page = (LayoutAwarePage) frame.Content;
                    if (page != null) page.Frame.Navigate(typeof (SettingsPage));
                });
                e.Request.ApplicationCommands.Add(userSettingsCommand);
            }

            var supportCommand = new SettingsCommand("Support", "Support", handler =>
            {
                var supportPane = new SupportFlyout();
                supportPane.Show();
            });
            e.Request.ApplicationCommands.Add(supportCommand);

            var aboutCommand = new SettingsCommand("About", loader.GetString("Settings_OptionLabels_About"), handler =>
            {
                var aboutPane = new About();
                aboutPane.Show();
            });
            e.Request.ApplicationCommands.Add(aboutCommand);
        }

        private void Application_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            //var exception = e.Exception;
            //string errorDetails = "e.Message:\n" + exception.Message + "\n\ne.Exception.StackTrace:\n" + exception.StackTrace + "\n\nexception.InnerException:\n" + exception.InnerException;

            // Use true to prevent process termination
            //e.Handled = true;

            /*StorageFolder folder = ApplicationData.Current.LocalFolder;
            StorageFile file = await folder.CreateFileAsync("ErroLog.txt",CreationCollisionOption.OpenIfExists);

            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
                {
                    using (DataWriter dataWriter = new DataWriter(outputStream))
                    {
                        //TODO: Replace "Bytes" with the type you want to write.
                        //dataWriter.WriteString("ErrorMessage: " + e.Message + "\n\nStackTrace: " + e.Exception.StackTrace + "\n\nInnerException: " + e.Exception.InnerException.ToString());
                        //dataWriter.DetachStream();
                    }
                    //await outputStream.FlushAsync();
                }
            }*/

            /*var frame = (Frame)Window.Current.Content;
            var page = (LayoutAwarePage)frame.Content;
            page.Frame.Navigate(typeof(ErrorPage), errorDetails);*/
        }
    }
}